#ifndef CLIB_CLIB_CONTAINER_VECTOR_H
#define CLIB_CLIB_CONTAINER_VECTOR_H

#include "../../base/clib_base.h"

CLIB_CPLUS_SUPPORT_START

/**
 * 可变数组对象
 * 是一个添加元素时自动扩展的动态数组。
 * 该数组支持在数组末尾常量时间插入和删除元素，以及常量时间访问。
 */
struct clib_container_vector;

/**
 * 可变数组配置对象
 */
struct clib_container_vector_conf {
    /**
     * 初始化容量
     */
    size_t capacity;

    /**
     * 内存分配函数
     * @param size 需要分配的大小
     * @return
     */
    void *(*mem_malloc_func)(size_t size);

    /**
     * 内存释放函数
     * @param block 块指针
     */
    void (*mem_free_func)(void *block);

    /**
     * 内存拷贝函数
     * @param target 目标
     * @param src 源
     * @param size 大小
     * @return
     */
    void *(*mem_copy_func)(void *target,const void *src, size_t size);
};

/**
 * 通过配置文件创建可变数组
 * @param conf 配置信息对象
 * @param out 创建的可变数组对象
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_create_with_conf(
        struct clib_container_vector_conf *conf,
        struct clib_container_vector **out);

/**
 * 销毁一个可变数组对象
 * @param vector 要销毁的可变数组对象
 */
void clib_container_vector_destroy(
        struct clib_container_vector *vector);

/**
 * 向可变数组尾部添加一个元素
 * @param vector  可变数组对象
 * @param element 要添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_add(
        struct clib_container_vector *vector,
        void *element);

/**
 * 指定索引添加元素
 * 如果指定索引有数据，则该索引后面的数据都将向后偏移
 * @param vector 可变数组对象
 * @param element 要添加的元素
 * @param index 要添加到的索引
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_add_with_index(
        struct clib_container_vector *vector,
        void *element,
        size_t index);

/**
 * 指定索引替换元素
 * 返回原来索引的指针数据 out
 * @param vector 可变数组对象
 * @param element 要添加的元素
 * @param index 要添加的索引
 * @param out 存储替换前的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_replace_with_index(
        struct clib_container_vector *vector,
        void *element,
        size_t index,
        void **out);

/**
 * 指定两个索引，交换这两个索引的数据指针
 * @param vector 可变数组对象
 * @param index1 索引1
 * @param index2索引2
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_swap_with_index(
        struct clib_container_vector *vector,
        size_t index1,
        size_t index2);

/**
 * 获取指定数据指针的第一个索引值
 * @param vector 可变数组对象
 * @param element 要查询的数据指针
 * @param index 存储查询出的索引
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_index_of(
        struct clib_container_vector *vector,
        void *element,
        size_t *index);

/**
 * 在可变数组中删除指定的数据指针，但不会释放，需要用户自行判断是否释放
 * @param vector 可变数组
 * @param element 要删除的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_remove(
        struct clib_container_vector *vector,
        void *element);


/**
 * 删除指定索引的数据
 * @param vector 可变数组
 * @param index 要删除的元素索引
 * @param out 存储删除之后的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_remove_with_index(
        struct clib_container_vector *vector,
        size_t index,
        void **out);

/**
 * 删除最后一个元素
 * @param vector  可变数组
 * @param out 存储删除之后的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_remove_last(
        struct clib_container_vector *vector,
        void **out);


/**
 * 根据索引查询数据
 * @param vector 可变数组
 * @param index 查询的索引
 * @param out 存储查询出的数据
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_get_with_index(
        struct clib_container_vector *vector,
        size_t index,
        void **out);


/**
 * 获取最后一个元素
 * @param vector 可变数组
 * @param out 存储查询出的数据
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_get_last(
        struct clib_container_vector *vector,
        void **out);

/**
 * 创建一个指定可变数组的子集可变数组
 * @param vector 可变数组对象
 * @param begin_index 开始索引
 * @param end_index 结束索引
 * @param out 新创建的可变数组
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_create_sub(
        struct clib_container_vector *vector,
        size_t begin_index,
        size_t end_index,
        struct clib_container_vector **out);

/**
 * 过滤可变数组，在指定的filer函数中，返回true代表不删除，false代表删除
 * out存储已经删除的数据指针
 * @param vector 可变数组
 * @param filter 过滤器
 * @param out 删除之后的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_vector_filter(struct clib_container_vector *vector,
                                 bool (*filter)(const void *),
                                 void **out);

/**
 * 将指定的可变数组数据进行翻转
 * @param vector 可变数组对象
 */
void clib_container_vector_reverse(struct clib_container_vector *vector);

/**
 * 将可变数组对象的容量进行修剪
 * 变为可以满足要求的最小容量
 * @param vector 可变数组对象
 * @return
 */
int clib_container_vector_trim_capacity(struct clib_container_vector *vector);


/**
 * 判断元素是否存在指定的可变数组对象中，
 * 并返回存在的个数
 * @param vector 可变数组对象
 * @param element 要查询的元素指针
 * @return
 * 存在 > 0
 * 不存在 0
 */
size_t clib_container_vector_contains(
        struct clib_container_vector *vector,
        void *element);

/**
 * 获取当前元素个数
 * @param vector 可变数组对象
 * @return
 */
size_t clib_container_vector_get_current_size(struct clib_container_vector *vector);


/**
 * 获取当前容量
 * @param vector 可变数组对象
 * @return
 */
size_t clib_container_vector_get_capacity(struct clib_container_vector *vector);


/**
 * 对元素进行排序
 * 需要用户自行指定比较函数
 * @param vector 可变数组对象
 * @param compare 比较函数
 */
void clib_container_vector_sort(
        struct clib_container_vector *vector,
        int (*compare)(const void *, const void *));

/**
 * map操作
 * @param vector 可变数组对象
 * @param map map函数
 */
void clib_container_vector_map(
        struct clib_container_vector *vector,
        void (*map)(void *e));


/**
 * reduce函数
 * @param vector 可变数组对象
 * @param reduce reduce函数
 * @param result reduce结果
 */
void clib_container_vector_reduce(
        struct clib_container_vector *vector,
        void (*reduce)(void *, void *, void *),
        void *result);

CLIB_CPLUS_SUPPORT_END

#endif //CLIB_CLIB_CONTAINER_VECTOR_H
